/*---------------------------------------------------------------------------------
	$Id: template.c,v 1.4 2005/09/17 23:15:13 wntrmute Exp $

	Basic Hello World

	$Log: template.c,v $
	Revision 1.4  2005/09/17 23:15:13  wntrmute
	corrected iprintAt in templates
	
	Revision 1.3  2005/09/05 00:32:20  wntrmute
	removed references to IPC struct
	replaced with API functions
	
	Revision 1.2  2005/08/31 01:24:21  wntrmute
	updated for new stdio support

	Revision 1.1  2005/08/03 06:29:56  wntrmute
	added templates


---------------------------------------------------------------------------------*/
#include <fat.h>
#include <nds.h>
#include <nds/arm9/console.h> //basic print funcionality
#include <nds/arm9/input.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>


#include "gmConfig.h"
#include "gmMachine.h"
#include "gmThread.h"
#include "gmTableObject.h"
#include "gmStringObject.h"
#include "gmHelpers.h"
#include "gmUtil.h"
#include "gmStringLib.h"
#include "gmMathLib.h"
#include "gmCall.h"

gmMachine* machine = new gmMachine;
int lastUpdateTime = 0;
static bool running=true;


void PrintCallback(gmMachine * a_machine, const char * a_string) {
        iprintf(a_string);
}

int GM_CDECL NdsDebugPrint(gmThread*a_thread)
{
        GM_CHECK_NUM_PARAMS(1);
        GM_CHECK_STRING_PARAM(message,0);
        iprintf(message);
        return GM_OK;
}

int GM_CDECL NdsDebugClear(gmThread*a_thread)
{
        consoleClear();
        return GM_OK;
}

gmFunctionEntry ndsBinds[] =
{
        {"debugPrint",NdsDebugPrint},
        {"debugClear",NdsDebugClear}
};

void InitGM()
{
        gmMachine::s_printCallback = PrintCallback;
        gmBindStringLib(machine);
        gmBindMathLib(machine);
        machine->RegisterLibrary(ndsBinds, sizeof(ndsBinds) / sizeof(ndsBinds[0]));

		//Set Key Enumerations
        machine->GetGlobals()->Set(machine, "KEY_A", gmVariable(KEY_A));
		machine->GetGlobals()->Set(machine, "KEY_B", gmVariable(KEY_B));
		machine->GetGlobals()->Set(machine, "KEY_SELECT", gmVariable(KEY_SELECT));
		machine->GetGlobals()->Set(machine, "KEY_START", gmVariable(KEY_START));
		machine->GetGlobals()->Set(machine, "KEY_RIGHT", gmVariable(KEY_RIGHT));
		machine->GetGlobals()->Set(machine, "KEY_LEFT", gmVariable(KEY_LEFT));
		machine->GetGlobals()->Set(machine, "KEY_UP", gmVariable(KEY_UP));
		machine->GetGlobals()->Set(machine, "KEY_DOWN", gmVariable(KEY_DOWN));
		machine->GetGlobals()->Set(machine, "KEY_R", gmVariable(KEY_R));
		machine->GetGlobals()->Set(machine, "KEY_L", gmVariable(KEY_L));
		machine->GetGlobals()->Set(machine, "KEY_X", gmVariable(KEY_X));
		machine->GetGlobals()->Set(machine, "KEY_Y", gmVariable(KEY_Y));

        lastUpdateTime=time(0);
}

void ShutdownGM()
{
        delete machine;
        machine=NULL;
}

void UpdateGM()
{
        int deltaTime = time(0) - lastUpdateTime;
        machine->Execute(deltaTime);
        lastUpdateTime=time(0);
}

void LoadScript(const char* file)
{
        FILE *input = fopen(file,"r");
        size_t result;

        fseek( input, 0L, SEEK_END );
        size_t lSize = ftell( input );
        rewind(input);

        char* script = new char[lSize+1];
        result=fread(script,1,lSize,input);
        if(result != lSize)
        {
                iprintf("Error reading file!\n");
                return;
        }
        script[lSize]=0;
        fclose(input);

        int errors = machine->ExecuteString(script, NULL, false, file);
        delete [] script;
        script = NULL;
        if(errors)
        {
                bool first = true; 
                const char *message; 
                while((message = machine->GetLog().GetEntry(first))) { 
                        iprintf(message);
                } 
                machine->GetLog().Reset();

        }
}

void DoInputStuff()
{
        gmCall  call;
		
		scanKeys();
		u16 keyDown = keysDown();
		u16 keyUp = keysUp();
		u16 keyHeld = keysHeld();
		
		/*iprintf("keyDown = %04X\n",keyDown);
		iprintf("keyUp = %04X\n",keyUp);
		iprintf("keyHeld = %04X\n",keyHeld);
		
		keyUp = 0;
		while( 0 == (keyUp & KEY_B) )
		{
			scanKeys();
			keyUp = keysUp();
		}*/
		
        if(keyDown)
        {
			//Call Pressed function
            if(call.BeginGlobalFunction(machine,"ButtonPressed"))
            {
                call.AddParamInt(keyDown);
                call.End();
            }
        }
        else if(keyHeld)
        {
            if(call.BeginGlobalFunction(machine,"ButtonHeld"))
            {
                call.AddParamInt(keyHeld);
                call.End();
            }
        }
        else if(keyUp)
        {
            if(call.BeginGlobalFunction(machine,"ButtonReleased"))
            {
                call.AddParamInt(keyUp);
                call.End();
            }
        }
}



//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------

	videoSetMode(0);	//not using the main screen
	videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);	//sub bg 0 will be used to print text
	vramSetBankC(VRAM_C_SUB_BG);

	SUB_BG0_CR = BG_MAP_BASE(31);

	BG_PALETTE_SUB[255] = RGB15(31,31,31);	//by default font will be rendered with color 255

	//consoleInit() is a lot more flexible but this gets you up and running quick
	consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);
	
	iprintf("\n\nLets try init fat\n");
	
	bool succ = fatInitDefault();
	if(!succ)
	{
		iprintf("\n\nCan't init fat!\n");
		while(1);
	}

	iprintf("Lets test GameMonkey!\n\n");
	
	InitGM();
    LoadScript("main.gm");
	
	while(running)
    {
        DoInputStuff();
        UpdateGM();
    }

    ShutdownGM();

	return 0;
}
